<template>
  <div 
    class="code-highlight-container"
    :class="{ editable: editable }"
    :data-max-height="maxHeight ? 'true' : null"
    :style="{ '--max-height': maxHeight }"
  >
    <!-- 可编辑模式 -->
    <div v-if="editable" class="editable-code-container">
      <textarea
        ref="textareaRef"
        v-model="localCode"
        @input="handleInput"
        @scroll="syncScroll"
        @wheel="handleWheel"
        @select="handleSelectionChange"
        @click="handleSelectionChange"
        @keyup="handleSelectionChange"
        class="code-textarea"
        :placeholder="placeholder"
        :style="{ fontSize: fontSize }"
      ></textarea>
      <pre 
        ref="highlightRef"
        class="code-highlight overlay" 
        :class="themeClass"
        :style="{ fontSize: fontSize }"
      ><code 
        :class="languageClass"
        v-html="highlightedCode"
      ></code></pre>
      <div v-if="showLineNumbers" class="line-numbers" :style="{ fontSize: fontSize }">
        <span 
          v-for="n in lineCount" 
          :key="n" 
          class="line-number"
        >{{ n }}</span>
      </div>
    </div>
    
    <!-- 只读模式 -->
    <div v-else class="readonly-code-container">
      <pre class="code-highlight" :class="themeClass" :style="{ fontSize: fontSize }"><code 
        ref="codeRef" 
        :class="languageClass"
        v-html="highlightedCode"
      ></code></pre>
      <div v-if="showLineNumbers" class="line-numbers" :style="{ fontSize: fontSize }">
        <span 
          v-for="n in lineCount" 
          :key="n" 
          class="line-number"
        >{{ n }}</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css' // 默认主题

const props = defineProps({
  code: {
    type: String,
    default: ''
  },
  language: {
    type: String,
    default: 'auto' // auto, json, xml, html, javascript, css, etc.
  },
  theme: {
    type: String,
    default: 'github' // github, monokai, atom-one-dark, etc.
  },
  showLineNumbers: {
    type: Boolean,
    default: true
  },
  maxHeight: {
    type: String,
    default: '400px'
  },
  editable: {
    type: Boolean,
    default: false
  },
  placeholder: {
    type: String,
    default: '请输入代码...'
  },
  fontSize: {
    type: String,
    default: '12px' // 可调整字体大小
  }
})

const emit = defineEmits(['update:code'])

const codeRef = ref(null)
const textareaRef = ref(null)
const highlightRef = ref(null)
const highlightedCode = ref('')
const localCode = ref('')

// 计算行数
const lineCount = computed(() => {
  const code = props.editable ? localCode.value : props.code
  if (!code) {
    return 1 // 完全空内容显示1行
  }
  if (code.trim() === '') {
    return Math.max(1, code.split('\n').length) // 空白内容按实际换行数计算
  }
  return code.split('\n').length
})



// 同步滚动
const syncScroll = () => {
  if (textareaRef.value && highlightRef.value) {
    highlightRef.value.scrollTop = textareaRef.value.scrollTop
    highlightRef.value.scrollLeft = textareaRef.value.scrollLeft
    
    // 同步行号滚动 - 行号不需要transform，让它们自然跟随容器滚动
    // 行号应该保持在原位，通过容器的overflow: auto来处理滚动
    const lineNumbers = textareaRef.value.parentElement?.querySelector('.line-numbers')
    if (lineNumbers) {
      // 重置transform，让行号保持在原始位置
      lineNumbers.style.transform = 'translateY(0px)'
    }
    
    // 强制重新计算布局
    highlightRef.value.offsetHeight
  }
}

// 处理容器滚动
const handleContainerScroll = () => {
  syncScroll()
}

// 自动调整textarea高度
const adjustTextareaHeight = () => {
  if (textareaRef.value) {
    // 重置高度以获取真实的scrollHeight
    textareaRef.value.style.height = 'auto'
    
    // 计算需要的高度
    const scrollHeight = textareaRef.value.scrollHeight
    const minHeight = 60 // 最小高度60px
    const newHeight = Math.max(scrollHeight, minHeight)
    
    // 设置新高度
    textareaRef.value.style.height = newHeight + 'px'
    
    // 同步overlay高度
    if (highlightRef.value) {
      highlightRef.value.style.height = newHeight + 'px'
    }
  }
}

// 处理输入时的滚动同步
const handleInput = (e) => {
  localCode.value = e.target.value
  emit('update:code', localCode.value)
  
  // 输入后调整高度和同步滚动
  nextTick(() => {
    adjustTextareaHeight()
    syncScroll()
    // 再次确保同步
    setTimeout(() => {
      syncScroll()
    }, 10)
  })
}

// 处理选择变化（光标位置变化）
const handleSelectionChange = () => {
  nextTick(() => {
    syncScroll()
  })
}

// 处理鼠标滚轮事件，确保只影响滚动而不是内容
const handleWheel = (e) => {
  if (textareaRef.value) {
    // 阻止默认的滚轮行为
    e.preventDefault()
    
    // 手动处理滚动
    const delta = e.deltaY
    textareaRef.value.scrollTop += delta
    
    // 同步滚动位置
    syncScroll()
  }
}

// 语言类名
const languageClass = computed(() => {
  if (props.language === 'auto') {
    return ''
  }
  return `language-${props.language}`
})

// 主题类名
const themeClass = computed(() => {
  return `hljs-theme-${props.theme}`
})

// 自动检测语言
const detectLanguage = (code) => {
  if (!code) return 'plaintext'
  
  // 尝试解析JSON
  try {
    JSON.parse(code)
    return 'json'
  } catch (e) {
    // 不是JSON，继续检测其他格式
  }
  
  // 检测XML/HTML
  if (code.trim().startsWith('<') && code.trim().endsWith('>')) {
    if (code.includes('<!DOCTYPE html>') || code.includes('<html')) {
      return 'html'
    }
    return 'xml'
  }
  
  // 检测JavaScript
  if (code.includes('function') || code.includes('=>') || code.includes('var ') || code.includes('let ') || code.includes('const ')) {
    return 'javascript'
  }
  
  // 检测CSS
  if (code.includes('{') && code.includes('}') && code.includes(':')) {
    return 'css'
  }
  
  return 'plaintext'
}

// 高亮代码
const highlightCode = () => {
  const code = props.editable ? localCode.value : props.code
  if (!code) {
    highlightedCode.value = ''
    return
  }
  
  try {
    let detectedLanguage = props.language
    if (props.language === 'auto') {
      detectedLanguage = detectLanguage(code)
    }
    
    if (detectedLanguage === 'plaintext') {
      highlightedCode.value = hljs.highlightAuto(code).value
    } else {
      highlightedCode.value = hljs.highlight(code, { language: detectedLanguage }).value
    }
  } catch (error) {
    console.warn('代码高亮失败:', error)
    highlightedCode.value = hljs.highlightAuto(code).value
  }
}

// 监听代码变化
watch(() => props.code, (newCode) => {
  if (props.editable) {
    localCode.value = newCode
  }
  highlightCode()
  
  // 如果是可编辑模式，调整高度
  if (props.editable) {
    nextTick(() => {
      adjustTextareaHeight()
    })
  }
}, { immediate: true })
watch(() => localCode.value, highlightCode)
watch(() => props.language, highlightCode)

onMounted(() => {
  highlightCode()
  
  // 如果是可编辑模式，调整高度
  if (props.editable) {
    nextTick(() => {
      adjustTextareaHeight()
      
      // 添加容器滚动监听
      const container = textareaRef.value?.closest('.code-highlight-container')
      if (container) {
        container.addEventListener('scroll', handleContainerScroll)
      }
    })
  }
})

// 组件卸载时清理监听器
onUnmounted(() => {
  if (props.editable && textareaRef.value) {
    const container = textareaRef.value.closest('.code-highlight-container')
    if (container) {
      container.removeEventListener('scroll', handleContainerScroll)
    }
  }
})
</script>

<style scoped lang="scss">
.code-highlight-container {
  position: relative;
  border: 1px solid #e1e8ed;
  border-radius: 6px;
  background: #f8f9fa;
  overflow: auto; // 允许滚动
  height: auto; // 自适应内容高度
  max-height: 500px; // 最大高度限制，超过就滚动
  
  &[data-max-height] {
    max-height: var(--max-height);
  }
  
  // 当容器滚动时，确保行号同步
  &::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }
  
  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
  }
  
  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
    
    &:hover {
      background: #a8a8a8;
    }
  }
  
  // 可编辑模式
  .editable-code-container {
    position: relative;
    height: auto; // 自适应内容高度
    min-height: 60px; // 最小高度
    overflow: visible; // 允许内容溢出
    resize: vertical; // 允许垂直拖动调整高度
    
    .code-textarea {
      position: relative; // 改为相对定位
      width: 100%;
      height: auto; // 自适应高度
      min-height: 60px; // 最小高度
      padding: 8px 12px;
      padding-left: 42px; // 精确对齐：40px行号宽度 + 2px边距
      margin: 0;
      border: none;
      outline: none;
      background: transparent;
      color: transparent;
      caret-color: #333;
      font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
      // font-size 由内联样式控制
      line-height: 1.5;
      white-space: pre;
      overflow: hidden; // 隐藏滚动条
      resize: none;
      z-index: 2;
      word-wrap: normal;
      word-break: normal;
      overflow-wrap: normal;
      
      // placeholder样式
      &::placeholder {
        color: #999 !important; // 强制覆盖transparent颜色
        opacity: 1 !important;
        font-style: italic;
        display: block;
        width: 100%;
        text-align: left;
      }
      
      // Firefox兼容
      &::-moz-placeholder {
        color: #999 !important; // 强制覆盖transparent颜色
        opacity: 1 !important;
        font-style: italic;
      }
      
      // Webkit兼容
      &::-webkit-input-placeholder {
        color: #999 !important; // 强制覆盖transparent颜色
        opacity: 1 !important;
        font-style: italic;
      }
    }
    
    .code-highlight.overlay {
      position: absolute; // 绝对定位，覆盖在textarea上
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 8px 12px; // 与textarea保持一致
      padding-left: 42px; // 与textarea保持一致：40px行号宽度 + 2px边距
      background: transparent; // 透明背景
      font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
      // font-size 由内联样式控制
      line-height: 1.5;
      white-space: pre;
      overflow: hidden; // 隐藏滚动条
      pointer-events: none;
      z-index: 1;
      box-sizing: border-box;
      border: none;
      outline: none;
      
      code {
        background: transparent;
        padding: 0;
        border: none;
        font-family: inherit;
        font-size: inherit;
        line-height: inherit;
      }
    }
  }
  
  // 只读模式
  .readonly-code-container {
    .code-highlight {
      margin: 0;
      padding: 16px;
      padding-left: 42px; // 与编辑模式保持一致：40px行号宽度 + 2px边距
      background: #ffffff;
      overflow-x: auto;
      font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
      // font-size 由内联样式控制
      line-height: 1.5;
      white-space: pre;
      
      code {
        background: transparent;
        padding: 0;
        border: none;
        font-family: inherit;
        font-size: inherit;
        line-height: inherit;
      }
    }
  }
  
  .line-numbers {
    position: absolute;
    top: 0;
    left: 0;
    width: 40px;
    height: auto; // 改为自动高度，让内容决定高度
    min-height: 100%; // 至少填满容器
    background: #f1f3f4;
    border-right: 1px solid #e1e8ed;
    padding: 8px 6px;
    font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
    // font-size 由内联样式控制，不在这里设置
    line-height: 1.5;
    color: #666;
    text-align: right;
    user-select: none;
    z-index: 3;
    box-sizing: border-box;
    overflow: visible; // 改为可见，让行号能够显示
    // 确保行号与代码同步滚动
    transform: translateY(0);
    
    .line-number {
      display: block;
      line-height: 1.5; // 确保与代码行高一致
      height: auto; // 自适应高度
      margin: 0; // 清除默认margin
      padding: 0; // 清除默认padding
      min-height: 1.5em; // 确保每个行号有最小高度
    }
  }
}

// 主题样式
.hljs-theme-github {
  .code-highlight {
    background: #ffffff;
  }
}

.hljs-theme-monokai {
  .code-highlight {
    background: #272822;
    color: #f8f8f2;
  }
  
  .line-numbers {
    background: #383830;
    border-right-color: #49483e;
    color: #90908a;
  }
}

.hljs-theme-atom-one-dark {
  .code-highlight {
    background: #282c34;
    color: #abb2bf;
  }
  
  .line-numbers {
    background: #21252b;
    border-right-color: #181a1f;
    color: #636d83;
  }
}

// 响应式
@media (max-width: 768px) {
  .code-highlight-container {
    .code-highlight {
      padding-left: 35px;
      // font-size 由内联样式控制
    }
    
    .line-numbers {
      width: 30px;
      // font-size 由内联样式控制
    }
  }
}
</style>